package com.zackeus.mvvm.utils;

import androidx.activity.result.ActivityResultCaller;
import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.NonNull;

import com.elvishew.xlog.XLog;
import com.journeyapps.barcodescanner.ScanContract;
import com.journeyapps.barcodescanner.ScanIntentResult;
import com.journeyapps.barcodescanner.ScanOptions;
import com.zackeus.mvvm.widget.zxing.QR.QrcodeActivity;

import java.util.LinkedList;
import java.util.Queue;

import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.subjects.PublishSubject;

/**
 * zxing 条码扫描封装
 * @name: RxZxing
 * @author: zz
 * @date: 2022/10/9
 */
public class RxZxing {

    private static final String LOG_TAG = RxZxing.class.getSimpleName();
    private final Queue<PublishSubject<ScanIntentResult>> mSubjects = new LinkedList<>();
    private final ActivityResultLauncher<ScanOptions> mLauncher;

    public RxZxing(@NonNull ActivityResultCaller caller) {
        mLauncher = caller.registerForActivityResult(new ScanContract(), result -> {
            PublishSubject<ScanIntentResult> subject = mSubjects.poll();
            if (subject == null) {
                XLog.tag(LOG_TAG).e("The zxing subject is empty.");
                return;
            }

            subject.onNext(result);
            subject.onComplete();
        });
    }

    public Observable<ScanIntentResult> scanQR() {
        return this.scanQR("二维码置于扫描框内");
    }

    /**
     * 扫描二维码
     * @param prompt
     * @return
     */
    public Observable<ScanIntentResult> scanQR(String prompt) {
        PublishSubject<ScanIntentResult> subject = PublishSubject.create();

        try {
            mSubjects.add(subject);
        } catch (Exception e) {
            XLog.tag(LOG_TAG).e("Zxing scan QR error.", e);
            return Observable.create(emitter -> emitter.onError(e));
        }

        mLauncher.launch(new ScanOptions()
                .setCaptureActivity(QrcodeActivity.class)
                .setDesiredBarcodeFormats(ScanOptions.QR_CODE)
                .setPrompt(prompt)
                .setOrientationLocked(Boolean.FALSE)
        );
        return subject;
    }
}
